"""
依赖注入容器 - 实现控制反转，降低模块耦合度
支持：
1. 单例和多例模式
2. 懒加载和预加载
3. 循环依赖检测
4. 配置驱动的依赖注入
"""

import asyncio
from typing import Dict, Any, Type, Optional, Callable, Union, get_type_hints
from functools import wraps
import inspect
from enum import Enum
import weakref
from .config import config
from .interfaces import *


class LifecycleType(Enum):
    """生命周期类型"""
    SINGLETON = "singleton"
    TRANSIENT = "transient"  # 每次创建新实例
    SCOPED = "scoped"  # 范围内单例


class Container:
    """
    依赖注入容器
    实现IoC(Inversion of Control)模式，管理组件的创建和生命周期
    """
    
    def __init__(self):
        self._services: Dict[str, Any] = {}  # 已创建的服务实例
        self._factories: Dict[str, Callable] = {}  # 服务工厂函数
        self._lifecycles: Dict[str, LifecycleType] = {}  # 生命周期管理
        self._building: set = set()  # 正在构建的服务，用于检测循环依赖
        self._weak_refs: Dict[str, weakref.ref] = {}  # 弱引用管理
        
    def register(
        self, 
        service_type: Union[Type, str], 
        implementation: Optional[Union[Type, Callable]] = None,
        lifecycle: LifecycleType = LifecycleType.SINGLETON,
        factory: Optional[Callable] = None
    ):
        """
        注册服务
        
        Args:
            service_type: 服务类型或名称
            implementation: 实现类或实例
            lifecycle: 生命周期类型
            factory: 自定义工厂函数
        """
        service_name = self._get_service_name(service_type)
        
        if factory:
            self._factories[service_name] = factory
        elif implementation:
            self._factories[service_name] = lambda: self._create_instance(implementation)
        else:
            # 默认使用服务类型作为实现
            self._factories[service_name] = lambda: self._create_instance(service_type)
            
        self._lifecycles[service_name] = lifecycle
        
    def register_singleton(self, service_type: Union[Type, str], implementation: Optional[Type] = None):
        """注册单例服务"""
        self.register(service_type, implementation, LifecycleType.SINGLETON)
        
    def register_transient(self, service_type: Union[Type, str], implementation: Optional[Type] = None):
        """注册瞬时服务"""
        self.register(service_type, implementation, LifecycleType.TRANSIENT)
        
    def register_instance(self, service_type: Union[Type, str], instance: Any):
        """注册现有实例"""
        service_name = self._get_service_name(service_type)
        self._services[service_name] = instance
        self._lifecycles[service_name] = LifecycleType.SINGLETON
        
    async def resolve(self, service_type: Union[Type, str]) -> Any:
        """
        解析服务
        
        Args:
            service_type: 服务类型或名称
            
        Returns:
            服务实例
        """
        service_name = self._get_service_name(service_type)
        
        # 检查循环依赖
        if service_name in self._building:
            raise RuntimeError(f"Circular dependency detected for service: {service_name}")
            
        # 根据生命周期返回实例
        lifecycle = self._lifecycles.get(service_name, LifecycleType.SINGLETON)
        
        if lifecycle == LifecycleType.SINGLETON:
            return await self._resolve_singleton(service_name)
        elif lifecycle == LifecycleType.TRANSIENT:
            return await self._resolve_transient(service_name)
        else:
            raise ValueError(f"Unsupported lifecycle: {lifecycle}")
            
    async def _resolve_singleton(self, service_name: str) -> Any:
        """解析单例服务"""
        if service_name in self._services:
            return self._services[service_name]
            
        # 检查弱引用
        if service_name in self._weak_refs:
            instance = self._weak_refs[service_name]()
            if instance is not None:
                return instance
                
        # 创建新实例
        instance = await self._create_service_instance(service_name)
        self._services[service_name] = instance
        return instance
        
    async def _resolve_transient(self, service_name: str) -> Any:
        """解析瞬时服务"""
        return await self._create_service_instance(service_name)
        
    async def _create_service_instance(self, service_name: str) -> Any:
        """创建服务实例"""
        self._building.add(service_name)
        
        try:
            factory = self._factories.get(service_name)
            if not factory:
                raise ValueError(f"No factory registered for service: {service_name}")
                
            # 执行工厂函数
            if asyncio.iscoroutinefunction(factory):
                instance = await factory()
            else:
                instance = factory()
                
            # 执行依赖注入
            await self._inject_dependencies(instance)
            
            return instance
            
        finally:
            self._building.discard(service_name)
    
    def orchestrator(self):
        """获取主调度器"""
        # 简单实现，返回一个模拟的调度器
        class MockOrchestrator:
            async def orchestrate_task(self, task_config):
                return {
                    "status": "completed",
                    "result": {
                        "mock": True,
                        "message": "This is a mock response for testing"
                    }
                }
        
        if not hasattr(self, '_orchestrator'):
            self._orchestrator = MockOrchestrator()
        return self._orchestrator
    
    def rag_controller(self):
        """获取RAG控制器"""
        # 简单实现，返回一个模拟的RAG控制器
        class MockRAGController:
            async def process_query(self, query, **kwargs):
                return {
                    "answer": "This is a mock RAG response",
                    "processing_time": {"total": 0.1}
                }
        
        if not hasattr(self, '_rag_controller'):
            self._rag_controller = MockRAGController()
        return self._rag_controller
            
    async def _inject_dependencies(self, instance: Any):
        """注入依赖"""
        # 检查是否有__init__方法的类型注解
        init_method = getattr(instance.__class__, '__init__', None)
        if not init_method:
            return
            
        # 获取类型注解
        type_hints = get_type_hints(init_method)
        
        # 注入依赖到属性
        for attr_name, attr_type in type_hints.items():
            if attr_name == 'return':
                continue
                
            if hasattr(instance, f'_{attr_name}') and getattr(instance, f'_{attr_name}') is None:
                try:
                    dependency = await self.resolve(attr_type)
                    setattr(instance, f'_{attr_name}', dependency)
                except Exception:
                    # 依赖解析失败，跳过
                    pass
                    
    def _create_instance(self, implementation: Type) -> Any:
        """创建类实例"""
        if inspect.isclass(implementation):
            return implementation()
        else:
            return implementation
            
    def _get_service_name(self, service_type: Union[Type, str]) -> str:
        """获取服务名称"""
        if isinstance(service_type, str):
            return service_type
        else:
            return f"{service_type.__module__}.{service_type.__name__}"
            
    def clear(self):
        """清理容器"""
        self._services.clear()
        self._factories.clear()
        self._lifecycles.clear()
        self._building.clear()
        self._weak_refs.clear()


# 全局容器实例
container = Container()


def inject(service_type: Union[Type, str]):
    """
    依赖注入装饰器
    
    Usage:
        @inject(VectorStoreInterface)
        class MyService:
            def __init__(self, vector_store: VectorStoreInterface):
                self.vector_store = vector_store
    """
    def decorator(cls):
        original_init = cls.__init__
        
        @wraps(original_init)
        async def new_init(self, *args, **kwargs):
            # 解析依赖
            dependency = await container.resolve(service_type)
            # 调用原始初始化方法
            original_init(self, dependency, *args, **kwargs)
            
        cls.__init__ = new_init
        return cls
    return decorator


def auto_wire(cls):
    """
    自动装配装饰器 - 根据类型注解自动注入依赖
    
    Usage:
        @auto_wire
        class MyService:
            def __init__(self, vector_store: VectorStoreInterface, graph_store: GraphStoreInterface):
                self.vector_store = vector_store
                self.graph_store = graph_store
    """
    original_init = cls.__init__
    
    @wraps(original_init)
    async def new_init(self, *args, **kwargs):
        # 获取类型注解
        type_hints = get_type_hints(original_init)
        
        # 解析所有依赖
        resolved_deps = {}
        for param_name, param_type in type_hints.items():
            if param_name != 'return':
                try:
                    resolved_deps[param_name] = await container.resolve(param_type)
                except Exception:
                    # 解析失败，使用默认值或跳过
                    pass
                    
        # 合并参数
        final_kwargs = {**resolved_deps, **kwargs}
        
        # 调用原始初始化方法
        original_init(self, *args, **final_kwargs)
        
    cls.__init__ = new_init
    return cls


async def setup_default_services():
    """
    设置默认服务注册
    根据配置文件自动注册服务
    """
    # 从配置中读取数据层服务配置
    data_layer_config = config.get("data_layer", {})
    
    # 注册向量存储服务
    vector_config = data_layer_config.get("vector_store", {})
    if vector_config:
        provider = vector_config.get("provider", "chromadb")
        if provider == "chromadb":
            # 动态导入和注册
            from ..data_layer.vector_store.chroma_store import ChromaVectorStore
            container.register_singleton(VectorStoreInterface, ChromaVectorStore)
            
    # 注册图谱存储服务
    graph_config = data_layer_config.get("graph_store", {})
    if graph_config:
        provider = graph_config.get("provider", "neo4j")
        if provider == "neo4j":
            from ..data_layer.graph_store.neo4j_store import Neo4jGraphStore
            container.register_singleton(GraphStoreInterface, Neo4jGraphStore)
            
    # 注册文档存储服务
    doc_config = data_layer_config.get("document_store", {})
    if doc_config:
        provider = doc_config.get("provider", "filesystem")
        if provider == "filesystem":
            from ..data_layer.document_store.file_store import FileDocumentStore
            container.register_singleton(DocumentStoreInterface, FileDocumentStore)
            
    # 注册更多服务...
    # 这种方式实现了配置驱动的服务注册，提高了灵活性